/**
 * @format
 * @Author: TC
 * @Date: 2023-03-18 18:05:42
 * @Last Modified by: TC
 * @Last Modified time: 2023-03-18 21:34:28
 */

import {
    color,
    director,
    easing,
    Graphics,
    instantiate,
    Layers,
    Node,
    Prefab,
    Tween,
    tween,
    UIOpacity,
    UITransform,
    v3,
    view,
    Widget,
} from "cc";
import { app } from "../../App";
import { IUIData } from "../../Common/BaseInterface";
import { mFrameEnumConst } from "../../Const/FrameEnumConst";
import { IBaseInterface, IWindowInterface } from "../../Interface/BaseInterface";
import { UIManager } from "../../Manager/UIManager";
import { BaseUI } from "../Component/BaseUI";
import { ASSERT_TYPE } from "../Res/ResConst";
import { IUIConfig } from "./UIInterface";

/**
 * 窗口状态
 */
export enum EUIStatus {
    OPENING, //打开中
    OPENED, //打开完成
    CLOSED, //已关闭
    CLOSED_PASSIVE, //被动关闭
}

/**
 * 窗口单位
 */
export class UIUnit implements IBaseInterface {
    private _uiCfg: IUIConfig = null;
    private _winNode: Node = null;
    private _uuid: number = 0;

    /**
     * 窗口状态
     */
    private _status: EUIStatus = EUIStatus.OPENING;
    public get status(): EUIStatus {
        return this._status;
    }
    public set status(s: EUIStatus) {
        this._status = s;
    }
    constructor(uiCfg: IUIConfig, uuid: number) {
        this._uuid = uuid;
        this._uiCfg = uiCfg;
    }

    /**
     * 打开窗口
     */
    public open(data: IUIData, cb: (comp: BaseUI) => void): void {
        this.status = EUIStatus.OPENING;
        const time = new Date();
        this.beforFirstOpen();
        app.resMgr.loadPrefab(this._uiCfg.bundleName, this._uiCfg.prefabPath, (pfb: Prefab) => {
            this._winNode = instantiate(pfb) as Node;
            const comp = this._winNode.getComponent(BaseUI);
            if (!comp) {
                app.log.error("窗口没有UI组件" + this._uiCfg.prefabPath);
                return;
            }
            this._addUIOpacity();
            comp.setData(data);
            const content = this._winNode.getChildByName("content");
            if (!content) {
                app.log.error("窗口没有content节点" + this._uiCfg.prefabPath);
                return;
            }
            content.setPosition(v3(0, 0, 0));
            this._addWidget();
            comp.setUIInfo(this);
            const parentNode: Node = app.sceneMgr.getCurrScene().getLayer(this._uiCfg.layer);
            parentNode.addChild(this._winNode);

            const delta = new Date().getTime() - time.getTime();
            app.log.log(`打开窗口${this._uiCfg.prefabPath}完成,耗时${delta / 1000}s`);
            this.status = EUIStatus.OPENED;
            this.afterFirstOpen();
            comp.openFirst();
            if (cb) cb(comp);
        });
    }

    private _addUIOpacity(): void {
        this._winNode.addComponent(UIOpacity).opacity = 255;
    }

    /**
     * 添加组件widget
     */
    private _addWidget(): void {
        const widget = this._winNode.getComponent(Widget) || this._winNode.addComponent(Widget);
        widget.isAlignBottom = true;
        widget.isAlignLeft = true;
        widget.isAlignRight = true;
        widget.isAlignTop = true;
        widget.left = 0;
        widget.right = 0;
        widget.top = 0;
        widget.bottom = 0;
    }

    /**
     * 第一次打开之前
     */
    private beforFirstOpen(): void {
        if (!this.uiCfg.noShowLoading) {
            app.uiMgr.showLoading();
        }
    }

    /**
     * 第一次打开之后
     */
    private afterFirstOpen(): void {
        app.uiMgr.hideLoading();
        // this._winNode.getChildByName("content").on(Node.EventType.TOUCH_END, () => {});
        const winSize = view.getVisibleSize();
        const wd: number = winSize.width;
        const ht: number = winSize.height;
        //遮罩层事件监听
        if (!this._uiCfg.noHasMask || this.uiCfg.fullScreen) {
            const maskNode: Node = new Node();
            maskNode.layer = Layers.Enum.UI_2D;
            maskNode.name = "maskNode";
            maskNode.addComponent(UITransform).setContentSize(winSize);
            const pen: Graphics = maskNode.addComponent(Graphics);
            pen.fillColor = this._uiCfg.maskColor || color(0, 0, 0, 190);
            pen.fillRect(-wd / 2, -ht / 2, wd, ht);
            this._winNode.addChild(maskNode);
            maskNode.setSiblingIndex(0);
            if (!this._uiCfg.noBlankClose && !this._uiCfg.fullScreen)
                maskNode.on(Node.EventType.TOUCH_END, () => {
                    app.uiMgr.closeUI(this._winNode.name, this.uuid);
                });
            else {
                if (!this._uiCfg.noMaskTouch) {
                    maskNode.on(Node.EventType.TOUCH_END, () => {});
                }
            }
        }
    }

    /**
     * 关闭窗口
     * @param passive 是否被动关闭
     */
    public close(passive: boolean): void {
        if (this._uiCfg.autoDestroy) {
            this._destroy();
        } else {
            this._hide(passive);
        }
    }

    /**
     * 销毁窗口
     */
    public destruoy(): void {
        this._destroy();
    }

    /**
     * 显示
     */
    public show(data?: IUIData): void {
        this.status = EUIStatus.OPENED;
        const widget = this._winNode.getComponent(Widget);
        widget.enabled = true;
        const op = this._winNode.getComponent(UIOpacity);
        op.opacity = 255;
        this._winNode.setPosition(v3(0, 0, 0));
        this._winNode.getComponent(BaseUI)?.setData(data);
        this._winNode.getComponent(BaseUI).openAgain();
        // this._winNode.active = true;
        app.log.log(`打开已存在窗口${this._uiCfg.prefabPath}完成`);
    }

    /**
     * 隐藏
     * @param passive 是否被动关闭
     */
    private _hide(passive: boolean): void {
        if (this.isClosed()) return;
        // this._winNode.active = false;
        const widget = this._winNode.getComponent(Widget);
        widget.enabled = false;
        const op = this._winNode.getComponent(UIOpacity);
        op.opacity = 0;
        this._winNode.setPosition(v3(-5000, 0, 0));
        this.status = passive ? EUIStatus.CLOSED_PASSIVE : EUIStatus.CLOSED;

        this._winNode.getComponent(BaseUI).onHide();
    }

    private _destroy(): void {
        this.release();
    }
    public get uiCfg(): IUIConfig {
        return this._uiCfg;
    }
    public get uuid(): number {
        return this._uuid;
    }

    /**
     * 获取窗口的UI脚本
     * @returns
     */
    public getUIComp(): BaseUI {
        return this._winNode?.getComponent(BaseUI);
    }

    /**
     * 获取窗口的UI节点
     * @returns
     */
    public getUINode(): Node {
        return this._winNode;
    }

    /**
     * 窗口是否处于关闭状态
     * @returns
     */
    public isClosed(): boolean {
        return this.status == EUIStatus.CLOSED || this.status == EUIStatus.CLOSED_PASSIVE;
    }
    release(): void {
        this._winNode.destroy();
        this._winNode = null;
    }
}
